package com.ruben;

import com.ruben.utils.Opt;
import org.springframework.data.util.Optionals;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @ClassName: OptionalDemo
 * @Description: 我还没有写描述
 * @Date: 2021/1/5 0005 20:47
 * *
 * @author: <achao1441470436@gmail.com>
 * @version: 1.0
 * @since: JDK 1.8
 */
public class OptionalDemo {
    public static void main(String[] args) {
        List<String> sss = Optionals.toStream(Optional.of("SSS")).map(String::toLowerCase).collect(Collectors.toList());
        System.out.println(sss);
        Optionals.mapIfAllPresent(Optional.of("SSS"), Optional.of("R"), String::concat).ifPresent(System.out::println);
        Opt.ofNullable("SSS")
                .peek(System.out::println)
                .map(d -> null)
                .peek(System.out::println);
    }

    private static void oldDemo() {
        String str = null;
        // 直接使用Optional.map去调用函数，避免空指针，其中的任意一个函数返回为空的话，则直接调用后面的orElseGet(String::new)并返回new String()执行的结果
        System.out.println(Optional.ofNullable(str).map(""::equals).map(Boolean::getClass).map(Class::getName).orElseGet(String::new));
        // 上面的方法，每次都需要使用.map去操作，比较繁琐，于是这里定义一个叫 avoidNPE 的函数去处理空指针异常
        // 使用方式如下
        System.out.println(avoidNPE(() -> Boolean.valueOf(str.equals("")).equals(Boolean.FALSE)).orElse(false));
        // 再来一个对比，更明显一点
        // 使用自定义的函数之前
        System.out.println(Optional.ofNullable(Arrays.asList()).map(List::stream).map(Stream::sorted).map(Stream::distinct).flatMap(Stream::findFirst).orElse("empty"));
        // 使用自定义的函数后 orElseThrow 如果值存在则返回，不存在抛出异常
        System.out.println(avoidNPE(() -> Arrays.asList().stream().sorted().distinct().findFirst().orElse("empty")).orElseThrow(() -> new RuntimeException("value not found")));
        List<String> list = null;
        // 同理，数组越界也可以自定义一个函数做相同处理 filter为过滤，就是再执行一次判断，如果返回true则继续之后的逻辑，否则直接返回Optional.EMPTY
        avoidNPEOrIOB(list, 5).filter(s -> s.length() > 2).map(String::hashCode).ifPresent(System.out::println);
    }


    /**
     * @MethodName: avoidNPEOrIOB
     * @Description: 避免空指针和数组越界
     * @Date: 2021/1/5 0005 21:14
     * *
     * @author: <achao1441470436@gmail.com>
     * @param: [list, index]
     * @returnValue: java.util.Optional<T>
     */
    public static <T> Optional<T> avoidNPEOrIOB(List<T> list, int index) {
        try {
            return Optional.ofNullable(list.get(index));
        } catch (NullPointerException | ArrayIndexOutOfBoundsException e) {
            return Optional.empty();
        }
    }

    /**
     * @MethodName: avoidNPE
     * @Description: 避免空指针
     * @Date: 2021/1/5 0005 21:14
     * *
     * @author: <achao1441470436@gmail.com>
     * @param: [supplier]
     * @returnValue: java.util.Optional<T>
     */
    public static <T> Optional<T> avoidNPE(Supplier<T> supplier) {
        try {
            return Optional.ofNullable(supplier.get());
        } catch (NullPointerException e) {
            return Optional.empty();
        }
    }

}
